package com.zhuxiaomei.websocket;

import com.alibaba.fastjson2.JSON;
import com.zhuxiaomei.dto.ws.WSResult;
import com.zhuxiaomei.entity.msg.CoupleBindMessage;
import com.zhuxiaomei.service.MessageService;
import com.zhuxiaomei.utils.MessageUtils;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hxm
 * @date 2024/12/20 21:44
 * @description
 */
@Component
@ServerEndpoint("/ws/{sid}")
@Slf4j
public class WebSocketServer {

    private static final String COUPLE_BONDING_APPLICATION = "5000";

    //存放会话对象
    private static final Map<String, Session> sessionMap = new HashMap();




    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext context){
        applicationContext = context;
    }

    @NotNull
    private static MessageService messageService(){
        return applicationContext.getBean(MessageService.class);
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        if (sessionMap.containsKey(sid)) {
            return; // 不再存储该连接
        }
        //根据sid查找当前是否有未接收的消息，如果有查询出来再次发送
        List<CoupleBindMessage> unReceiveCoupleBindMessage = messageService().selectMessage(null, sid, "1");
        //根据sid查找当前是否有发送未接收的消息，如果有查询出来再次发送
        List<CoupleBindMessage> sentCoupleBindMessage = messageService().selectMessage(sid, null, "1");
        sendMessage(session, unReceiveCoupleBindMessage);
        sendMessage(session, sentCoupleBindMessage);
        log.info("客户端{}建立链接", sid);
        sessionMap.put(sid, session);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        WSResult wsResult = JSON.parseObject(message, WSResult.class);
        Session session = sessionMap.get(wsResult.getTo());
        // 情侣绑定关系
        if (COUPLE_BONDING_APPLICATION.equals(wsResult.getType())) {
            messageService().handleCoupleBind(session, wsResult);
        }

    }

    /**
     * 连接关闭调用的方法
     *
     * @param
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
//        System.out.println("连接断开:" + sid);
        log.info("连接断开{}", sid);
        sessionMap.remove(sid);
    }

    /**
     * 群发
     *
     * @param message
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void sendMessage(Session session, List<CoupleBindMessage> coupleBindMessages) {
        for (CoupleBindMessage coupleBindMessage : coupleBindMessages){
            WSResult wsResult = WSResult.builder()
                    .type(coupleBindMessage.getType())
                    .from(coupleBindMessage.getFromAccount())
                    .to(coupleBindMessage.getToAccount())
                    .message(coupleBindMessage.getData())
                    .build();
            try {
                session.getBasicRemote().sendText(MessageUtils.getMessage(wsResult));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

}
